import axios, { AxiosResponse, AxiosRequestConfig, Method } from 'axios';
import QS from 'qs'

/* 创建axios的实例 */
const service = axios.create({
    baseURL: process.env.VUE_APP_BASE_URL || '',
    timeout: 5000 * 2, 
});


/* 防止重复提交，利用axios的cancelToken */
interface PendingType {
    url?: string; //✔️️ 可以设置可选属性 并非必要的 可写可不写
    method?: Method;
    readonly  params: object; //✔️ 设置只读属性
    data: object;
    cancel: Function;
}

// 声明一个数组用于存储每个ajax请求的取消函数和ajax标识
const pending: Array<PendingType> = []; 
const CancelToken = axios.CancelToken;

// 移除重复操作
const removePending = (config: AxiosRequestConfig) => {
    for (const key in pending) {
        const item: number = +key;
        const list: PendingType = pending[key];
        // 当前请求在数组中存在时执行函数体
        if (list.url === config.url && list.method === config.method && JSON.stringify(list.params) === JSON.stringify(config.params) && JSON.stringify(list.data) === JSON.stringify(config.data)) {
            // 执行取消操作
            list.cancel('操作太频繁，请稍后再试');
            // 从数组中移除记录
            pending.splice(item, 1);
        }
    }
};

/* 添加请求拦截器 */
service.interceptors.request.use(
    (request: AxiosRequestConfig) => {
        if(request.method === 'post'){
            request.data = QS.stringify(request.data)
        }
        request.headers['Content-type'] = 'application/json'
        removePending(request);
        request.cancelToken = new CancelToken((c: Function) => {
            pending.push({ url: request.url, method: request.method, params: request.params, data: request.data, cancel: c });
        });
        return request;
    }, 
    (error) => {
        return Promise.reject(error);
    });
interface Err {
    response: object;
    config: any;
    message: string;
}
/* 添加响应拦截器 */
service.interceptors.response.use(
    (response: AxiosResponse) => {
        removePending(response.config);
        // 获取返回数据，并处理。按自己业务需求修改。下面只是个demo
        const res = response.data;

        if (res.code !== 200) {
            if (res.code === 401) {
                if (location.hash === '#/') {
                    return res;
                } else {
                    location.href = '/#/';
                }
            }
            return Promise.reject('error');
        } else {
            return res;
        }
    },
    (error: Err) => {
        // 异常处理
        console.error('异常', error)
        const response = error.response;

        // 超时重新请求
        const config = error.config;
        // 全局的请求次数,请求的间隙
        const [RETRY_COUNT, RETRY_DELAY] = [3, 1000];

        if (config && RETRY_COUNT) {
            // 设置用于跟踪重试计数的变量
            config.__retryCount = config.__retryCount || 0;
            // 检查是否已经把重试的总数用完
            if (config.__retryCount >= RETRY_COUNT) {
                return Promise.reject(response || { message: error.message });
            }
            // 增加重试计数
            config.__retryCount++;
            // 创造新的Promise来处理指数后退
            const backoff = new Promise((resolve) => {
                setTimeout(() => {
                    resolve();
                }, RETRY_DELAY || 1);
            });
            // service重试请求的Promise
            return backoff.then(() => {
                return service(config);
            });
        }

        // eslint-disable-next-line
        return Promise.reject(response || { message: error.message });
    },
);

export default service;
